<template>
  <div class="app-container">
    <PlatformHeader />
    <!-- 顶部日期选择器 -->
    <div class="header">
      <div class="time-control-panel">
        <!-- 隐藏式日期选择器 -->
        <div class="hidden-date-picker" @click.stop="toggleDatePicker">
          <div class="picker-trigger">
            <i class="el-icon-time"></i>
            <span class="trigger-text">选择日期</span>
          </div>

          <transition name="el-zoom-in-top">
            <div class="date-picker-dropdown" v-show="showDatePicker" @click.stop>
              <el-date-picker
                v-model="dateRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="yyyy-MM-dd"
                class="dark-date-picker"
                :picker-options="pickerOptions"
                @change="handleDateChange"
                popper-class="custom-select-dropdown"
              />
            </div>
          </transition>
        </div>
        <el-button
          class="mode-switch-btn"
          @click="toggleDisplayMode"
          :style="getRecordButtonImage()"
          :type="displayMode === 'monthly' ? 'primary' : ''"
        >
          <i :class="displayMode === 'normal' ? 'el-icon-data-analysis' : 'el-icon-view'"></i>
          {{ displayMode === 'normal' ? '月度分析' : '常规视图' }}
        </el-button>
        <div class="breadcrumb">
          <Bread
            style="padding: 0;"
            :items="breadcrumbItems"
            @item-click="handleBreadcrumbClick"
            :isWide="true"
          />
        </div>
      </div>
    </div>

    <!-- 主内容区 - 三栏布局 -->
    <div class="main-content">
      <!-- 左侧面板 - ECharts图表 -->
      <div class="panel left-panel">
        <div class="panel-header">
          <h3 class="panel-title glowing-text">{{ displayMode === 'normal' ? (chartType === 'gender' ? '人群分类统计' : '各年龄组统计') : '月度统计' }}</h3>
          <div class="panel-actions panel-left">
            <el-tooltip content="导出Excel" placement="top">
              <el-button
                size="mini"
                @click="exportLeftTable"
                circle
                class="my-icon">
                <span class="export-btn"></span>
              </el-button>
            </el-tooltip>
            <el-tooltip :content="chartType === 'gender' ? '切换为年龄组' : '切换为人群'" placement="top" v-if="displayMode === 'normal'">
              <el-button
                size="mini"
                @click="toggleChartType"
                :type="chartType === 'gender' ? 'primary' : ''"
                circle
                class="my-icon">
                <span class="detail"></span>
              </el-button>
            </el-tooltip>
            <el-tooltip :content="viewModes.left === 'chart' ? '切换为表格视图' : '切换为图表视图'" placement="top">
              <el-button
                size="mini"
                @click="toggleViewMode('left')"
                :type="viewModes.left === 'table' ? 'primary' : ''"
                circle
                class="my-icon">
                <span class="totable"></span>
              </el-button>
            </el-tooltip>
          </div>
        </div>
        <div class="panel-body">
          <div v-if="loading" class="chart-loading">
            <i class="el-icon-loading"></i> 数据加载中...
          </div>
          <template v-else>
            <div ref="chartContainer" style="width: 100%; height: 100%;" v-show="viewModes.left === 'chart'"></div>
            <el-table
              :data="leftTableData"
              style="width: 380px; height: 100%;margin: 0 auto"
              v-show="viewModes.left === 'table'"
              :header-cell-style="tableHeaderStyle"
              :cell-style="tableCellStyle"
              v-loading="loading"
            >
              <el-table-column prop="name" :label="displayMode === 'normal' ? (chartType === 'gender' ? '人群' : '年龄组') : '月份'"></el-table-column>
              <el-table-column prop="manvalue" label="男合格率"></el-table-column>
              <el-table-column prop="womanvalue" label="女合格率"></el-table-column>
              <el-table-column prop="totalvalue" label="总合格率"></el-table-column>
            </el-table>
          </template>
        </div>
      </div>

      <!-- 中间面板 -->
      <div class="panel center-panel" style="background: transparent;">
        <div class="panel-body">
          <SimpleCounter :count="uploadCount" :type="'passrate'"/>
          <div style="width: 100%; height: calc(100% - 99px);" v-show="viewModes.center === 'chart'">
            <Map
              :currentMapCode="currentMapCode"
              :currentMap="currentMap"
              :mapData="mapData"
              :type="'passrate'"
              @city-click="handleCityClick"
            />
          </div>
        </div>
      </div>

      <!-- 右侧面板 - ECharts图表 -->
      <div class="panel right-panel">
        <div class="panel-header">
          <h3 class="panel-title glowing-text">{{ displayMode === 'normal' ? '城乡分类统计' : '区域统计' }}</h3>
          <div class="panel-actions panel-right">
            <el-tooltip v-if="displayMode != 'normal' && viewModes.right !== 'table'" :content="isSorted ? '恢复默认' : '从高到低排序'" placement="top">
              <el-button
                size="mini"
                @click="sort"
                circle
                class="my-icon">
                <span class="sort"></span>
              </el-button>
            </el-tooltip>
            <el-tooltip content="导出Excel" placement="top">
              <el-button
                size="mini"
                @click="exportRightTable"
                circle
                class="my-icon">
                <span class="export-btn"></span>
              </el-button>
            </el-tooltip>
            <el-tooltip :content="viewModes.right === 'chart' ? '切换为表格视图' : '切换为图表视图'" placement="top">
              <el-button
                size="mini"
                @click="toggleViewMode('right')"
                :type="viewModes.right === 'table' ? 'primary' : ''"
                circle
                class="my-icon">
                <span class="totable"></span>
              </el-button>
            </el-tooltip>
          </div>
        </div>
        <div class="panel-body">
          <div v-if="loading" class="chart-loading">
            <i class="el-icon-loading"></i> 数据加载中...
          </div>
          <template v-else>
            <div ref="urbanRuralChart" style="width: 100%; height: 100%;" v-show="viewModes.right === 'chart'"></div>
            <el-table
              :data="rightTableData"
              style="width: 380px; height: 100%;margin: 0 auto"
              v-show="viewModes.right === 'table'"
              :header-cell-style="tableHeaderStyle"
              :cell-style="tableCellStyle"
              v-loading="loading"
            >
              <el-table-column prop="name" :label="displayMode === 'normal' ? '城乡' : '机构'"></el-table-column>
              <el-table-column prop="manvalue" label="男合格率"></el-table-column>
              <el-table-column prop="womanvalue" label="女合格率"></el-table-column>
              <el-table-column prop="totalvalue" label="总合格率"></el-table-column>
            </el-table>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { debounce } from 'lodash-es';
import * as echarts from 'echarts';
import {
  getAgegrouppassrate,
  getAgebracketpassrate,
  getUrbanandruralpassrate,
  getMonthpassrate,
  getNextdeptpassrate,
  getTotalpassrate
} from "../../../api/monitormanage/passrate";
import { getUserProfile } from "../../../api/system/user";
import Bread from '../../../components/Bread/index.vue';
import Map from '../../../components/Map/index.vue';
import PlatformHeader from '../../../components/PlatformHeader/index.vue';
import SimpleCounter from '../../../components/SimpleCounter/index.vue';
import { getDept } from "../../../api/system/dept";
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
import normal from '@/views/assets/images/normal.png'
import monthly from '@/views/assets/images/monthly.png'

// 图表配置常量
const CHART_CONFIG = {
  gender: {
    colors: ['rgba(62, 252, 234, 0.9)', 'rgba(255, 135, 28, 0.9)'],
    gradient: {
      male: [
        { offset: 0, color: 'rgba(62, 252, 234, 0.9)' },
        { offset: 1, color: 'rgba(1, 130, 255, 0.2)' }
      ],
      female: [
        { offset: 0, color: 'rgba(255, 135, 28, 0.9)' },
        { offset: 1, color: 'rgba(156, 90, 4, 0.2)' }
      ]
    }
  },
  urbanRural: {
    maleGradient: [
      { offset: 0, color: '#3EFCEA' },
      { offset: 1, color: '#0182FF' }
    ],
    femaleGradient: [
      { offset: 0, color: '#FFBC2F' },
      { offset: 1, color: '#9C5A04' }
    ]
  }
};

export default {
  components: {
    Bread,
    Map,
    PlatformHeader,
    SimpleCounter
  },
  data() {
    return {
      dateRange: [],
      chartInstance: null,
      urbanRuralChart: null,
      deptId: '',
      chartType: 'gender',
      displayMode: 'normal',
      loading: false,
      viewModes: {
        left: 'chart',
        center: 'chart',
        right: 'chart'
      },
      chartData: {
        gender: {
          loaded: false,
          xData: [],
          manvalue: [],
          womanvalue: [],
          tableData: []
        },
        ageBracket: {
          loaded: false,
          yAxisData: [],
          seriesData: [],
          tableData: []
        },
        urbanRural: {
          loaded: false,
          yAxisData: [],
          manvalue: [],
          womanvalue: [],
          tableData: []
        },
        monthly: {
          loaded: false,
          xData: [],
          seriesData: [],
          tableData: []
        },
        nextDept: {
          loaded: false,
          yData: [],
          totalValue: [],
          manValue: [],
          womanValue: [],
          tableData: []
        }
      },
      user: {},
      currentMap: '',
      currentMapCode: '',
      queryParams: {
        year: '',
        testtime: '',
        deptid: '',
        city: '',
        tablename: '',
        organizationCode: '',
        starttime: '',
        endtime: '',
      },
      year: '',
      testtime: '',
      organizationCode: '',
      mapData: [],
      breadcrumbItems: [],
      showDatePicker: false,
      pickerOptions: {
        disabledDate: (time) => {
          // 如果没有选择开始日期或者已经清除了选择，只禁用未来日期
          if (!this.startYear) {
            return time.getTime() > Date.now();
          }

          // 如果已经选择了开始日期，限制只能选择同一年份
          const timeYear = time.getFullYear();
          return time.getTime() > Date.now() || timeYear !== this.startYear;
        },
        onPick: ({ maxDate, minDate }) => {
          if (minDate) {
            // 保存选中的开始日期年份
            this.startYear = minDate.getFullYear();
          } else {
            // 如果没有选择日期，清除年份限制
            this.startYear = null;
          }
        },
        shortcuts: [{
          text: '最近一周',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
            picker.$emit('pick', [start, end]);
          }
        }, {
          text: '最近一个月',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
            picker.$emit('pick', [start, end]);
          }
        }, {
          text: '最近三个月',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
            picker.$emit('pick', [start, end]);
          }
        },{
          text: '本年至今', //
          onClick(picker) {
            const end = new Date();
            const start = new Date(end.getFullYear(), 0, 1);
            picker.$emit('pick', [start, end]);
          }
        }]
      },
      isSorted: false,
      originalData: null,
      uploadCount: 0,
      alternativeColorPieces: [
        { gte: 95.0, lte: 100.00, label: '95.0-100', color: '#0467B8' },
        { gte: 90.00, lt: 95.00, label: '90.0-94.9', color: '#0385D0' },
        { gte: 85.00, lt: 90.00, label: '85.0-89.9', color: '#019FE8' },//8
        { gte: 80.00, lt: 85.00, label: '80.0-84.9', color: '#0A9FBD' },
        { gte: 75.00, lt: 80.00, label: '75.0-79.9', color: '#079C98' },//6
        { gte: 70.00, lt: 75.00, label: '70.0-74.9', color: '#029B6C' },
        { gte: 65.00, lt: 70.00, label: '65.0-69.9', color: '#009D40' },//4
        { gte: 60.00, lt: 65.00, label: '60.0-64.9', color: '#23AE3B' },
        { gte: 40.00, lt: 60.00, label: '40.0-59.9', color: '#93C224' },
        { gte: 0.00, lt: 40.00, label: '0-39.9', color: '#CDDC07' }
      ],
    };
  },
  computed: {
    leftTableData() {
      if (this.displayMode === 'normal') {
        return this.chartType === 'gender'
          ? this.chartData.gender.tableData
          : this.chartData.ageBracket.tableData;
      } else {
        return this.chartData.monthly.tableData;
      }
    },
    rightTableData() {
      return this.displayMode === 'normal'
        ? this.chartData.urbanRural.tableData
        : this.chartData.nextDept.tableData;
    },
    tableHeaderStyle() {
      return {
        background: 'transparent',
        color: '#fff',
        borderBottom: '1px solid #fff'
      };
    },
    tableCellStyle() {
      return {
        background: 'transparent',
        color: '#fff',
        borderBottom: '1px solid transparent',
      };
    },
    allDataLoaded() {
      if (this.displayMode === 'normal') {
        return (this.chartType === 'gender' ? this.chartData.gender.loaded : this.chartData.ageBracket.loaded) &&
          this.chartData.urbanRural.loaded;
      } else {
        return this.chartData.monthly.loaded && this.chartData.nextDept.loaded;
      }
    }
  },
  watch: {
    allDataLoaded(newVal) {
      if (newVal) {
        this.loading = false;
      }
    }
  },
  created() {
    this.testtime = this.formattedDate();
    this.year = new Date().getFullYear();
  },
  mounted() {
    this.initData();
    this.initCharts();
    this.handleResize = debounce(this.handleResize, 300);
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    this.disposeCharts();
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    async fetchTotalPassRate() {
      try {
        // 根据是否有city参数决定传递哪些参数
        const params = {
          year: this.year,
          testtime: this.testtime,
          starttime: this.queryParams.starttime,
          endtime: this.queryParams.endtime
        };

        if (this.queryParams.city) {
          params.city = this.queryParams.city;
        } else {
          params.deptid = this.queryParams.deptid;
          params.organizationCode = this.queryParams.organizationCode;
        }

        const response = await getTotalpassrate(params);
        this.uploadCount = response?.data?.totalvalue || 0;
        return response;
      } catch (error) {
        console.error('获取总合格率失败:', error);
        this.uploadCount = 0;
        throw error;
      }
    },
    sort() {
      if (!this.isSorted) {
        this.originalData = {
          yData: [...this.chartData.nextDept.yData],
          totalValue: [...this.chartData.nextDept.totalValue]
        };

        const indexedData = this.chartData.nextDept.totalValue.map((value, index) => ({
          value,
          index
        }));

        indexedData.sort((a, b) => b.value - a.value);

        this.chartData.nextDept.yData = indexedData.map(item =>
          this.chartData.nextDept.yData[item.index]
        );
        this.chartData.nextDept.totalValue = indexedData.map(item => item.value);

        this.isSorted = true;
      } else {
        this.chartData.nextDept.yData = [...this.originalData.yData];
        this.chartData.nextDept.totalValue = [...this.originalData.totalValue];
        this.isSorted = false;
      }

      this.renderNextDeptChart();
    },
    toggleViewMode(panel) {
      // 只切换当前面板的视图模式，不影响其他面板
      this.viewModes[panel] = this.viewModes[panel] === 'chart' ? 'table' : 'chart';

      // 只更新当前面板的图表，不重新初始化其他面板
      if (this.viewModes[panel] === 'chart') {
        this.$nextTick(() => {
          if (panel === 'left') {
            this.updateLeftChart();
          } else if (panel === 'right') {
            this.updateRightChart();
          }
        });
      }
    },
    formattedDate() {
      const date = new Date();
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      return `${year}-${month}-${day}`;
    },
    async getUser() {
      try {
        const response = await getUserProfile();
        this.user = response.data;
        this.queryParams.deptid = response.data.deptId;
        const deptResponse = await getDept(response.data.deptId);
        const orgCode = String(deptResponse.data.organizationcode).padEnd(6, '0');
        const deptName = deptResponse.data.deptName;
        this.breadcrumbItems = [{ value: orgCode, title: deptName }];
        this.currentMapCode = orgCode;
        this.currentMap = deptName;
        this.queryParams.organizationCode = orgCode;
      } catch (error) {
        console.error('获取用户信息失败:', error);
        throw error;
      }
    },
    async initData() {
      try {
        this.loading = true;
        await this.getUser();

        // 设置基本参数
        this.queryParams.year = this.year;
        this.queryParams.testtime = this.testtime;

        // 只调用一次获取总合格率
        await this.fetchTotalPassRate();
        await this.fetchAllData();
      } catch (error) {
        console.error('初始化数据失败:', error);
        this.$message.error('数据加载失败');
        this.loading = false;
      }
    },
    async fetchAllData() {
      try {
        Object.keys(this.chartData).forEach(key => {
          this.chartData[key].loaded = false;
        });

        const requests = [
          this.fetchChartData('gender', getAgegrouppassrate),
          this.fetchChartData('ageBracket', getAgebracketpassrate),
          this.fetchChartData('urbanRural', getUrbanandruralpassrate),
          this.fetchChartData('monthly', getMonthpassrate),
          this.fetchChartData('nextDept', getNextdeptpassrate)
        ];
        await Promise.all(requests);
      } catch (error) {
        console.error('数据获取失败:', error);
        this.$message.error('获取数据失败');
      }
    },
    async fetchChartData(chartType, apiMethod) {
      try {
        // 根据是否有city参数决定传递哪些参数
        const params = {
          year: this.year,
          testtime: this.testtime,
          starttime: this.queryParams.starttime,
          endtime: this.queryParams.endtime
        };

        if (this.queryParams.city) {
          params.city = this.queryParams.city;
        } else {
          params.deptid = this.queryParams.deptid;
          params.organizationCode = this.queryParams.organizationCode;
        }

        const response = await apiMethod(params);
        this.processChartData(chartType, response);
        this.chartData[chartType].loaded = true;
        if(chartType ==='nextDept'){
          if(response.data != null && response.data.length > 0) {
            const transformedData = response.data.map(({ totalvalue, name }) => ({
              VALUE: totalvalue,
              NAME: name
            }));
            this.mapData = transformedData;
          } else {
            this.mapData = [];
            this.$message.error(response.message || '获取下级机构数据失败');
          }
        }
        this.$nextTick(() => {
          this.updateCharts();
        });
      } catch (error) {
        console.error(`获取${chartType}数据失败:`, error);
        this.chartData[chartType].loaded = true;
      }
    },
    processChartData(chartType, response) {
      const result = response.Result || response.data || [];

      switch (chartType) {
        case 'gender':
          this.chartData.gender = {
            loaded: true,
            xData: result.map(item => item.name),
            manvalue: result.map(item => item.manvalue),
            womanvalue: result.map(item => item.womanvalue),
            totalvalue: result.map(item => item.totalvalue),
            tableData: result.map(item => ({
              name: item.name,
              manvalue: item.manvalue,
              womanvalue: item.womanvalue,
              totalvalue: item.totalvalue
            }))
          };
          break;

        case 'ageBracket':
          this.chartData.ageBracket = {
            loaded: true,
            yAxisData: result.map(item => item.name),
            seriesData: result.map(item => item.totalvalue),
            tableData: result.map(item => ({
              name: item.name,
              manvalue: item.manvalue,
              womanvalue: item.womanvalue,
              totalvalue: item.totalvalue
            }))
          };
          break;

        case 'urbanRural':
          this.chartData.urbanRural = {
            loaded: true,
            yAxisData: result.map(item => item.name),
            manvalue: result.map(item => item.manvalue),
            womanvalue: result.map(item => item.womanvalue),
            totalvalue: result.map(item => item.totalvalue),
            tableData: result.map(item => ({
              name: item.name,
              manvalue: item.manvalue,
              womanvalue: item.womanvalue,
              totalvalue: item.totalvalue
            }))
          };
          break;

        case 'monthly':
          this.chartData.monthly = {
            loaded: true,
            xData: result.map(item => item.name + '月'),
            seriesData: result.map(item => item.totalvalue),
            tableData: result.map(item => ({
              name: item.name + '月',
              manvalue: item.manvalue,
              womanvalue: item.womanvalue,
              totalvalue: item.totalvalue
            }))
          };
          break;

        case 'nextDept':
          this.chartData.nextDept = {
            loaded: true,
            yData: result.map(item => item.name),
            totalValue: result.map(item => item.totalvalue),
            manValue: result.map(item => item.manvalue),
            womanValue: result.map(item => item.womanvalue),
            tableData: result.map(item => ({
              name: item.name,
              manvalue: item.manvalue,
              womanvalue: item.womanvalue,
              totalvalue: item.totalvalue
            }))
          };
          break;
      }
    },
    async handleCityClick(cityName) {
      try {
        this.loading = true;

        // 更新参数，清除deptid和organizationCode，只保留city
        this.queryParams = {
          ...this.queryParams,
          city: cityName,
          deptid: '',
          organizationCode: ''
        };

        // 获取总合格率数据
        const response = await getTotalpassrate({
          year: this.year,
          testtime: this.testtime,
          city: cityName,
          starttime: this.queryParams.starttime,
          endtime: this.queryParams.endtime
        });

        if (response.parameter && response.message == true) {
          const orgCode = response.parameter.organizationCode.padEnd(6, '0');
          this.currentMapCode = orgCode;
          this.currentMap = cityName;
          this.breadcrumbItems.push({ value: orgCode, title: cityName });
          this.uploadCount = response?.data?.totalvalue || 0;
          await this.fetchAllData();
        }else{
          this.loading = false;
          this.$message.error(response.message);
        }
      } catch (error) {
        console.error('处理城市点击失败:', error);
        this.$message.error('加载城市数据失败');
        this.loading = false;
      }
    },
    async handleBreadcrumbClick(clickedItem) {
      try {
        this.loading = true;
        const index = this.breadcrumbItems.findIndex(item => item.value === clickedItem.value);
        if (index === -1) return;

        const isLastItem = index === this.breadcrumbItems.length - 1;
        if (!isLastItem) {
          this.breadcrumbItems = this.breadcrumbItems.slice(0, index + 1);
          const cityName = clickedItem.title;

          if (index === 0) {
            // 点击的是第一个面包屑，恢复初始状态
            this.queryParams = {
              ...this.queryParams,
              city: '',
              deptid: this.user.deptId,
              organizationCode: this.queryParams.organizationCode
            };
            this.currentMapCode = this.queryParams.organizationCode;
            this.currentMap = clickedItem.title;
          } else {
            // 点击的是中间的面包屑，只保留city参数
            this.queryParams = {
              ...this.queryParams,
              city: cityName,
              deptid: '',
              organizationCode: ''
            };
          }

          // 获取总合格率数据
          const response = await getTotalpassrate({
            year: this.year,
            testtime: this.testtime,
            city: cityName,
            starttime: this.queryParams.starttime,
            endtime: this.queryParams.endtime
          });

          if (response.parameter && response.message == true) {
            const orgCode = response.parameter.organizationCode.padEnd(6, '0');
            this.currentMapCode = orgCode;
            this.currentMap = cityName;
            this.uploadCount = response?.data?.totalvalue || 0;
          }else {
            this.loading = false;
            this.$message.error(response.message);
          }
          await this.fetchAllData();
        }
      } catch (error) {
        console.error('处理面包屑点击失败:', error);
        this.$message.error('加载数据失败');
        this.loading = false;
      }
    },
    resetQueryParams() {
      // 重置查询参数，保留必要参数
      this.queryParams = {
        ...this.queryParams,
        city: '',
        tablename: '',
      };
      this.isSorted = false;
    },
    initCharts() {
      // 初始化图表实例，但不重新渲染所有图表
      if (!this.chartInstance && this.$refs.chartContainer) {
        this.chartInstance = echarts.init(this.$refs.chartContainer);
      }
      if (!this.urbanRuralChart && this.$refs.urbanRuralChart) {
        this.urbanRuralChart = echarts.init(this.$refs.urbanRuralChart);
      }
    },
    disposeCharts() {
      this.disposeChart(this.chartInstance);
      this.disposeChart(this.urbanRuralChart);
    },
    disposeChart(chart) {
      if (chart && !chart.isDisposed()) {
        chart.dispose();
      }
    },
    updateCharts() {
      // 更新所有图表
      this.updateLeftChart();
      this.updateRightChart();
    },
    updateLeftChart() {
      // 只更新左侧图表
      if (!this.chartInstance) {
        this.initCharts();
        return;
      }

      if (this.displayMode === 'normal') {
        if (this.chartType === 'gender' && this.chartData.gender.loaded) {
          this.renderGenderChart();
        } else if (this.chartData.ageBracket.loaded) {
          this.renderAgeBracketChart();
        }
      } else if (this.chartData.monthly.loaded) {
        this.renderMonthlyChart();
      }
    },
    updateRightChart() {
      // 只更新右侧图表
      if (!this.urbanRuralChart) {
        this.initCharts();
        return;
      }

      if (this.displayMode === 'normal' && this.chartData.urbanRural.loaded) {
        this.renderUrbanRuralChart();
      } else if (this.chartData.nextDept.loaded) {
        this.renderNextDeptChart();
      }
    },
    renderGenderChart() {
      const { xData, manvalue, womanvalue,totalvalue } = this.chartData.gender;

      const option = {
        backgroundColor: '',
        color: CHART_CONFIG.gender.colors,
        tooltip: {
          className: 'custom-echarts-tooltip',
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
          formatter: function(params) {
            const male = params[0];
            const female = params[1];
            const currentIndex = male.dataIndex;
            const currentTotal = totalvalue[currentIndex];

            if (!male && !female) return '';

            const date = male?.axisValue || female?.axisValue;

            let html = `
      <div class="tooltip-title">${date}</div>
    `;

            if (male) {
              html += `
        <div class="tooltip-item">
          <span class="tooltip-marker" style="background: ${CHART_CONFIG.gender.colors[0]}"></span>
          <span>${male.seriesName}: ${male.value}</span>
        </div>
      `;
            }

            if (female) {
              html += `
        <div class="tooltip-item">
          <span class="tooltip-marker" style="background: ${CHART_CONFIG.gender.colors[1]}"></span>
          <span>${female.seriesName}: ${female.value}</span>
        </div>
      `;
            }

            html += `
      <div class="tooltip-total">总体: ${currentTotal}</div>
    `;

            return html;
          }
        },
        legend: {
          data: ['男性', '女性'],
          textStyle: { color: '#fff' },
          left: 'center',
          top: "0"
        },
        grid: {
          left: '10%',
          right: '15%',
          top: '10%',
          bottom: '5%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: xData,
          axisLine: {
            lineStyle: { color: '#fff' }
          },
          axisLabel: {
            color: '#fff',
            rotate: xData.some(name => name.length > 4) ? 30 : 0,
            interval: 0
          },
          axisTick: { show: false },
          splitLine: { show: false }
        },
        yAxis: {
          type: 'value',
          splitLine: { show: false },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: {
            color: '#fff',
            formatter: '{value} '
          },
        },
        series: [
          {
            name: '男性',
            type: 'bar',
            barWidth: '28%',
            data: manvalue,
            itemStyle: {
              borderRadius: [4, 4, 0, 0],
              color:  CHART_CONFIG.gender.colors[0]
            },
            label: {
              show: true,
              position: 'top',
              color: '#fff'
            }
          },
          {
            name: '女性',
            type: 'bar',
            barWidth: '28%',
            data: womanvalue,
            itemStyle: {
              borderRadius: [4, 4, 0, 0],
              color:CHART_CONFIG.gender.colors[1]
            },
            label: {
              show: true,
              position: 'top',
              color: '#fff'
            }
          }
        ]
      };

      this.chartInstance.setOption(option, true);
    },
    renderAgeBracketChart() {
      const { yAxisData, seriesData } = this.chartData.ageBracket;
      const maxValue = Math.max(...seriesData, 1);

      const option = {
        grid: {
          left: '8%',
          right: '8%',
          bottom: '2%',
          top: '0%',
          containLabel: true
        },
        tooltip: {
          className: 'custom-echarts-tooltip',
          trigger: 'axis',
          axisPointer: { type: 'none' },
          formatter: function(params) {
            const param = params[0];
            if (!param) return '';

            return `
      <div class="tooltip-title">${param.name}</div>
      <div class="tooltip-item">
        <span class="tooltip-marker" style="background: rgba(36,207,233,0.9)"></span>
        <span>合格率: ${param.value.toLocaleString()}</span>
      </div>
    `;
          }
        },
        backgroundColor: '',
        xAxis: {
          show: false,
          type: 'value',
          max: maxValue
        },
        yAxis: [{
          type: 'category',
          inverse: true,
          axisLabel: {
            show: true,
            textStyle: {
              color: '#fff'
            },
          },
          splitLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          axisLine: {
            show: false
          },
          data: yAxisData
        }, {
          type: 'category',
          inverse: true,
          axisTick: 'none',
          axisLine: 'none',
          show: true,
          axisLabel: {
            textStyle: {
              color: '#ffffff',
              fontSize: '12'
            },
            formatter: function(value) {
              return value.toLocaleString();
            },
          },
          data: seriesData
        }],
        series: [{
          name: '人数',
          type: 'bar',
          zlevel: 1,
          itemStyle: {
            normal: {
              barBorderRadius: 30,
              color:"#00ffff"
            },
          },
          barWidth: 20,
          data: seriesData
        },
          {
            name: '背景',
            type: 'bar',
            barWidth: 20,
            barGap: '-100%',
            data: Array(yAxisData.length).fill(maxValue),
            itemStyle: {
              normal: {
                color: 'rgba(220, 220, 220, 0.5)',
                barBorderRadius: 30,
              }
            },
          }]
      };

      this.chartInstance.setOption(option, true);
    },
    renderUrbanRuralChart() {
      const { yAxisData, manvalue, womanvalue } = this.chartData.urbanRural;
      const option = {
        backgroundColor: "",
        grid: {
          left: '25%',
          right: '15%',
          top: '3%',
          bottom: '5%'
        },
        legend: {
          data: ["男性", "女性"],
          top: "0%",
          textStyle: {
            color: "#fff",
            fontSize: 16
          }
        },
        barWidth: 22,
        barGap: '70%',
        barCategoryGap: '10%',
        xAxis: {
          type: 'value',
          splitLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          axisLine: {
            show: false
          },
          axisLabel: {
            show: false
          },
        },
        yAxis: {
          type: 'category',
          data: yAxisData,
          inverse: true,
          axisLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: false
          },
          axisLabel: {
            formatter: function(value) {
              value = String(value).trim();
              const len = value.length;

              switch (len) {
                case 2:
                  return value.split('').join(' ');
                case 4:
                  return `${value[0]} ${value[1]}\n${value[2]} ${value[3]}`;
                case 5:
                  return `${value[0]} ${value[1]}\n${value[2]} ${value[3]} ${value[4]}`;
                case 7:
                case 8:
                  return value.match(/.{1,3}/g)
                    .map(group => group.split('').join(' '))
                    .join('\n');
                default:
                  return value;
              }
            },
            textStyle: {
              color: "#fff",
              fontSize: 16,
              fontWeight: 600
            },
            lineHeight: 20
          },
        },
        series: [
          {
            type: 'bar',
            name: "男性",
            itemStyle: {
              normal: {
                label: {
                  show: true,
                  formatter: '{c}',
                  position: 'right',
                  textStyle: {
                    color: "#8AFFFA",
                    fontSize: 16,
                    fontWeight: 600
                  }
                },
                color: new echarts.graphic.LinearGradient(1, 0, 0, 0, CHART_CONFIG.urbanRural.maleGradient),
                borderWidth: 2,
                barBorderRadius: [0, 15, 15, 0]
              }
            },
            data: manvalue
          },
          {
            type: 'bar',
            name: "女性",
            itemStyle: {
              normal: {
                label: {
                  show: true,
                  formatter: '{c}',
                  position: 'right',
                  textStyle: {
                    color: "#FFBA38",
                    fontSize: 16,
                    fontWeight: 600
                  }
                },
                color: new echarts.graphic.LinearGradient(1, 0, 0, 0, CHART_CONFIG.urbanRural.femaleGradient),
                borderWidth: 2,
                barBorderRadius: [0, 15, 15, 0]
              }
            },
            data: womanvalue
          }
        ]
      };

      this.urbanRuralChart.setOption(option, true);
    },
    renderMonthlyChart() {
      const { xData, seriesData } = this.chartData.monthly;

      const getColorByRate = (rate) => {
        for (const piece of this.alternativeColorPieces) {
          if (piece.lte !== undefined) {
            if (rate >= piece.gte && rate <= piece.lte) {
              return piece.color;
            }
          }
          else if (rate >= piece.gte && rate < piece.lt) {
            return piece.color;
          }
        }
        return '#9ee9ff';
      };

      const option = {
        backgroundColor: '',
        grid: {
          left: '8%',
          right: '8%',
          bottom: '5%',
          top: '3%',
          containLabel: true
        },
        xAxis: {
          data: xData,
          axisTick: {
            show: false
          },
          axisLine: {
            lineStyle: {
              color: 'rgba(255, 129, 109,.1)',
              width: 1
            }
          },
          axisLabel: {
            textStyle: {
              color: '#fff',
              fontSize: 12
            }
          }
        },
        yAxis: [{
          axisTick: {
            show: false
          },
          axisLine: {
            lineStyle: {
              color: 'rgba(255, 129, 109, 0.1)',
              width: 1
            }
          },
          axisLabel: {
            textStyle: {
              color: '#fff',
            },
            formatter: '{value}'
          },
          splitArea: {
            areaStyle: {
              color: 'rgba(255,255,255,.5)'
            }
          },
          splitLine: {
            show: true,
            lineStyle: {
              color: 'rgba(255, 129, 109, 0.1)',
              width: 0.5,
              type: 'dashed'
            }
          }
        }],
        series: [{
          type: 'bar',
          barWidth: '60%',
          barCategoryGap: '0%',
          label: {
            show: true,
            position: 'top',
            distance: 15,
            color: '#08DFFE',
            fontWeight: 'bolder',
            fontSize: 15,
            formatter: '{c}'
          },
          itemStyle: {
            color:'#08DFFE',
            emphasis: {
              opacity: 1
            }
          },
          data: seriesData
        }]
      };

      this.chartInstance.setOption(option, true);
    },
    renderNextDeptChart() {
      const { yData, totalValue } = this.chartData.nextDept;
      const dataCount = yData.length;
      const isVertical = dataCount < 5;

      const getColorByRate = (rate) => {
        for (const piece of this.alternativeColorPieces) {
          if (piece.lte !== undefined) {
            if (rate >= piece.gte && rate <= piece.lte) {
              return piece.color;
            }
          }
          else if (rate >= piece.gte && rate < piece.lt) {
            return piece.color;
          }
        }
        return '#9ee9ff';
      };

      const processedYData = yData.map(name => {
        if (name.length > 6) return name.substring(0, 6) + '...';
        return name;
      });

      const processedXData = yData.map(name => {
        if (name.length > 10) return name.substring(0, 10) + '...';
        return name;
      });

      const baseOption = {
        animation: false,
        tooltip: {
          className: 'custom-echarts-tooltip',
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            shadowStyle: { color: 'rgba(0, 0, 0, 0.1)' }
          },
          backgroundColor: 'rgba(255, 255, 255, 0.9)',
          borderColor: '#eee',
          borderWidth: 1,
          padding: [10, 15],
          textStyle: {
            color: '#333',
            fontSize: 14
          },
          formatter: function(params) {
            const date = params[0].axisValue;
            let html = `<div class="tooltip-title">${date}</div>`;

            params.forEach(param => {
              html += `
        <div class="tooltip-item">
          <span class="tooltip-marker" style="background: ${param.color}"></span>
          <span class="tooltip-name">${param.seriesName}</span>
          <span class="tooltip-value">${param.value}</span>
        </div>
      `;
            });

            return html;
          }
        },
        legend: { show: false },
        grid: {
          left: '10%',
          right: '15%',
          top: '2%',
          bottom: '5%',
          containLabel: true
        },
        series: [{
          name: '合格率',
          type: 'bar',
          barWidth: '60%',
          data: totalValue.map((item, i) => ({
            value: item,
            itemStyle: {
              color: getColorByRate(item),
              borderRadius: isVertical ? [4, 4, 0, 0] : [0, 4, 4, 0]
            }
          })),
          label: {
            show: true,
            position: isVertical ? 'top' : 'right',
            color: '#fff',
            fontSize: 14,
            fontWeight: 'bold',
            offset: isVertical ? [0, -2] : [10, 0],
            formatter: '{c}',
            fontFamily: 'Arial, sans-serif'
          },
          emphasis: {
            itemStyle: { opacity: 0.8 },
            label: { fontSize: 16 }
          },
          animationDuration: 1500,
          animationEasing: 'elasticOut'
        }]
      };

      const axisOption = isVertical
        ? {
          xAxis: {
            type: 'category',
            data: processedXData,
            axisLabel: {
              color: 'rgba(255, 255, 255, 0.7)',
              fontSize: 12,
              interval: 0,
              rotate: dataCount > 3 ? 30 : 0
            },
            axisLine: {
              lineStyle: { color: 'rgba(255, 255, 255, 0.3)' }
            },
            axisTick: { show: false }
          },
          yAxis: {
            type: 'value',
            max: 100,
            splitLine: {
              lineStyle: { color: 'rgba(255, 255, 255, 0.2)', type: 'dashed' }
            },
            axisLabel: {
              color: 'rgba(255, 255, 255, 0.7)',
              fontSize: 12,
              formatter: '{value}'
            },
            axisLine: { show: false },
            axisTick: { show: false }
          }
        }
        : {
          xAxis: {
            type: 'value',
            max: 100,
            splitLine: {
              lineStyle: { color: 'rgba(255, 255, 255, 0.2)', type: 'dashed' }
            },
            axisLabel: {
              color: 'rgba(255, 255, 255, 0.7)',
              fontSize: 12,
              formatter: '{value}'
            },
            axisTick: { show: false },
            axisLine: {
              show: true,
              lineStyle: { color: 'rgba(255, 255, 255, 0.3)' }
            }
          },
          yAxis: {
            type: 'category',
            inverse: true,
            data: processedYData,
            axisLine: { show: false },
            axisTick: { show: false },
            axisLabel: {
              fontSize: 14,
              color: '#fff',
              align: 'right',
              margin: 10,
              width: 120,
              overflow: 'truncate',
              interval: 0,
              fontFamily: 'Arial, sans-serif'
            }
          }
        };

      const option = { ...baseOption, ...axisOption };

      if (!this.urbanRuralChart) {
        const chartHeight = isVertical
          ? 400
          : Math.max(400, dataCount * 30);

        this.urbanRuralChart = echarts.init(
          this.$refs.urbanRuralChart,
          null,
          { height: chartHeight }
        );
      }

      this.urbanRuralChart.setOption(option, true);
    },
    toggleChartType() {
      // 切换图表类型时，确保左侧面板显示图表视图
      this.chartType = this.chartType === 'gender' ? 'ageBracket' : 'gender';
      this.viewModes.left = 'chart'; // 强制切换到图表视图
      this.$nextTick(() => {
        this.updateLeftChart(); // 只更新左侧图表
      });
    },
    toggleDisplayMode() {
      // 切换显示模式时强制切换到图表视图
      this.viewModes.left = 'chart';
      this.viewModes.right = 'chart';

      this.displayMode = this.displayMode === 'normal' ? 'monthly' : 'normal';
      this.$nextTick(() => {
        this.updateCharts();
      });
    },
    getRecordButtonImage() {
      if (this.displayMode === 'normal') {
        return "backgroundImage:url(" + normal + ");";
      } else {
        return "backgroundImage:url(" + monthly + ");";
      }
    },
    handleResize() {
      if (this.chartInstance && !this.chartInstance.isDisposed()) {
        this.chartInstance.resize();
      }
      if (this.urbanRuralChart && !this.urbanRuralChart.isDisposed()) {
        this.urbanRuralChart.resize();
      }
    },
    handleDateChange(val) {
      if (val && val.length === 2) {
        const startDate = new Date(val[0]);
        const endDate = new Date(val[1]);

        if (startDate.getFullYear() !== endDate.getFullYear()) {
          this.$message.error('开始时间和结束时间必须是同一年');
          this.dateRange = [];
          this.queryParams.starttime = '';
          this.queryParams.endtime = '';
          return;
        }

        this.queryParams.starttime = val[0];
        this.queryParams.endtime = val[1];
      } else {
        this.queryParams.starttime = '';
        this.queryParams.endtime = '';
      }

      // 先获取总合格率数据，再获取其他数据
      this.fetchTotalPassRate().then(() => {
        this.fetchAllData();
      });

      this.pickerOptions.disabledDate = (time) => {
        return time.getTime() > Date.now();
      };
    },
    exportToExcel(tableData, fileName) {
      const wb = XLSX.utils.book_new();

      const header = Object.keys(tableData[0]);
      const data = tableData.map(row => {
        return header.map(key => row[key]);
      });

      data.unshift(header.map(key => {
        switch(key) {
          case 'name': return '年龄组';
          case 'manvalue': return '男合格率';
          case 'womanvalue': return '女合格率';
          case 'totalvalue': return '总合格率';
          default: return key;
        }
      }));

      const ws = XLSX.utils.aoa_to_sheet(data);
      XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');

      const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
      saveAs(new Blob([wbout], { type: 'application/octet-stream' }), `${fileName}.xlsx`);
    },
    exportLeftTable() {
      this.exportToExcel(this.leftTableData, this.displayMode === 'normal'
        ? (this.chartType === 'gender' ? '人群分类统计' : '各年龄组统计')
        : '月度统计');
    },
    exportRightTable() {
      this.exportToExcel(this.rightTableData, this.displayMode === 'normal'
        ? '城乡分类合格率统计'
        : '区域统计');
    },
    toggleDatePicker() {
      this.showDatePicker = !this.showDatePicker
    },
  }
};
</script>

<style scoped lang="scss">
.app-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  overflow: hidden;
  background: url('../../assets/images/bga.png');
  background-size: 100% 100%;
  padding: 16px;
  box-sizing: border-box;
  padding-top: 0;
}

.main-content {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  gap: 0px;
}

.panel {
  display: flex;
  flex-direction: column;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
  overflow: hidden;
  border-radius: 4px;

  &-header {
    display: flex;
    padding: 10px 16px;
    padding-bottom: 30px;
    justify-content: center;
    padding-top: 20px;
  }

  &-title {
    margin: 0;
    font-size: 22px;
    font-weight: 500;
    color: #fff;
    letter-spacing: 2px;
  }

  &-body {
    flex: 1;
    padding: 0;
    overflow: hidden;
    position: relative;
  }

  &-actions {
    display: flex;
    gap: 2px;
    position: absolute;
    top:20px;
  }
  &-left {
    left: 10px;
  }
  &-right {
    right: 10px;
  }
}

.left-panel {
  flex: 0 0 22%;
  min-width: 0;
  background-image:url('../../assets/images/left-panel.png');
  background-size: 100% 100%;
  position: relative;
  .panel-body{
    padding-bottom: 10px;
  }
}

.right-panel {
  flex: 0 0 22%;
  min-width: 0;
  background-image:url('../../assets/images/right-panel.png');
  background-size: 100% 100%;
  position: relative;
  .panel-body{
    padding-bottom: 10px;
  }
}

.center-panel {
  flex: 1;
  background: transparent !important;

  .panel-header {
    justify-content: space-between;
  }
}

.chart-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #fff;
  font-size: 16px;

  i {
    margin-right: 8px;
    font-size: 20px;
  }
}

.toggle-icon {
  margin-left: 8px;
  transition: transform 0.1s;

  &:hover {
    transform: rotate(90deg);
  }

  i {
    font-size: 14px;
  }
}

.header {
  padding: 12px 0;
  margin-bottom: 0px;

  .time-control-panel {
    display: flex;
    align-items: center;
    border-radius: 8px;
    padding: 8px 16px;
    position: relative;
    .date-picker-wrapper {
      display: flex;
      align-items: center;
      margin-right: 20px;

      i {
        color: #3EFCEA;
        font-size: 18px;
        margin-right: 12px;
      }
    }

    .dark-date-picker {
      width: 300px;

      ::v-deep .el-range-input {
        background: transparent;
        color: #8AFFFA;
        font-size: 14px;
      }

      ::v-deep .el-range-separator {
        color: #3EFCEA;
        font-weight: normal;
      }

      ::v-deep .el-range__close-icon,
      ::v-deep .el-range__icon {
        color: #3EFCEA;
      }

      ::v-deep .el-range-editor {
        background: rgba(3, 18, 69, 0.8);
        border: 1px solid #024BBE;
        border-radius: 4px;
        padding: 5px 15px;
        box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
      }

      ::v-deep .el-range-editor.is-active {
        border-color: #3EFCEA;
        box-shadow: 0 0 5px rgba(62, 252, 234, 0.5);
      }
    }

    .mode-switch-btn {
      background: transparent;
      border: 1px solid #3EFCEA;
      color: #8AFFFA;
      padding: 8px 15px;
      border-radius: 4px;
      transition: all 0.1s;
      background-size: 100% 100%;
      background-position: center;
      border: none;
      color: transparent!important;

      i {
        margin-right: 6px;
        font-size: 16px;
      }

      &.el-button--primary {
        border-color: #0182FF;
        color: #fff;
      }
    }
  }
}
.breadcrumb {
  width: 900px;
  height: 50px;
  line-height: 50px;
  font-size: 24px;
  color: #e6e6e6;
  text-align: center;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -25px;
  margin-left: -450px;
}
.el-table{
  background-color: transparent;
}
::v-deep .el-table__body-wrapper{
  overflow: auto;
  height: 100%;
}
.my-icon {
  padding: 6px !important;
  background: transparent;
  border:none ;

  .el-icon {
    display: none;
  }

  .export-btn,.totable,.detail,.sort{
    display: block;
    width: 18px;
    height: 18px;
    background-size: 100% 100%;
    background-repeat: no-repeat;
    background-position: center;
    background-image: url('../../assets/images/export-btn.png');
  }
  .totable{
    background-image: url('../../assets/images/totable.png');
  }
  .detail{
    background-image: url('../../assets/images/detail.png');
  }
  .sort{
    background-image: url('../../assets/images/sort.png');
  }
}

.hidden-date-picker {
  position: relative;
  display: inline-block;
  margin-right: 20px;
  cursor: pointer;
  user-select: none;
  .picker-trigger {
    width: 110px;
    height: 32px;
    background-image:url('../../assets/images/timeslect.png');
    background-size: 100% 100%;
    background-position: center;
    border: none;
    color: transparent!important;
  }

  .date-picker-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 10;
    padding-top: 5px;

    ::v-deep .el-range-editor {
      background: rgba(0,106,253);
      border: 1px solid rgba(0,106,253, 0.5);
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
    }
  }
}
::v-deep .el-table tr{
  background:transparent;
}
::v-deep .el-table {
  .el-table__row {
    background-color: transparent !important;
    border-bottom: 1px solid #fff;
    background-size: 100% 100% !important;
  }

  .el-table__row:nth-child(even) {
    background: transparent url('../../assets/images/even-bg.png') no-repeat center center !important;
    background-size: 100% 100% !important;

    .el-table__cell {
      background-color: transparent !important;
    }
  }

  .el-table__row:hover {
    td {
      background-color: rgba(0, 0, 0, 0.1) !important;
    }
  }
}
::v-deep .el-table::before {
  height: 0px;
}
::v-deep .el-table__body-wrapper::-webkit-scrollbar {
  width: 0 !important;
  height: 0 !important;
}

::v-deep .el-table__body-wrapper {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.glowing-text {
  font-weight: bold;
  color: #ffffff;
  text-shadow: 0 0 5px #00a8ff,
  0 0 10px #00a8ff,
  0 0 15px #00a8ff;
  animation: glow 1.5s ease-in-out infinite alternate;
}

@keyframes glow {
  from {
    text-shadow: 0 0 5px #00a8ff,
    0 0 10px #00a8ff,
    0 0 15px #00a8ff;
  }
  to {
    text-shadow: 0 0 10px #00a8ff,
    0 0 20px #00a8ff,
    0 0 30px #00a8ff;
  }
}
</style>
